
#include "Vista.h"
#include <iostream>

#define MUSICA_FONDO 0
#define MUSICA_EVENTO 1

#define MUSICA_DEL_NIVEL 0
#define MUSICA_DE_INVENCIBILIDAD 1

#if INSTALANDO
#define PATH_RES PATH_RESOURCES
#else
#define PATH_RES "../Resources/"
#endif

Vista::Vista(SDL_Rect* rectPersonaje, Pantalla* pantalla, int anchoNivel, int altoNivel) {
	
	this->rectPersonaje = rectPersonaje;
	this->pantalla = new Pantalla(pantalla->getAncho(), pantalla->getAlto(), pantalla->getMargenScrollX());
	this->anchoNivel = anchoNivel;
	this->altoNivel = altoNivel;
	fondoNivel = NULL;
	fondo_estatico = NULL;
	camara = new Camara(this->pantalla, this->rectPersonaje);
	
	string path_res = PATH_RES;
	this->font14 = TTF_OpenFont((path_res+"fontArial.ttf").c_str(), 14 );
	this->font32 = TTF_OpenFont((path_res+"fontMario.ttf").c_str(), 32 );
	this->font54 = TTF_OpenFont((path_res+"fontMario.ttf").c_str(), 54 );
	srand(time(NULL));
	elegirFondo();
}

Vista::~Vista() {
	 
	SDL_FreeSurface(pantalla->getSuperficie());
	
	mapaImagenes.clear();

	delete pantalla;
	delete camara;
}

bool Vista::CrearSuperficiePantalla()
{
	SDL_Surface *superficiePantalla = NULL;

	superficiePantalla = SDL_SetVideoMode(pantalla->getAncho(), pantalla->getAlto()+25, 32, SDL_SWSURFACE);

	if( superficiePantalla == NULL )
	{
		//LOGUEAR("No se pudo inicializar la pantalla.",3);
		return NULL;
	}
	
	SDL_WM_SetCaption( "Biza Kong", NULL );

	pantalla->setSuperficie(superficiePantalla);
	//LOGUEAR("La pantalla fue inicializada.",0);
	
	return true;
}

void Vista::CrearMapaSonidos(vector<infoSonido_t> infoSonidos, string path, int personaje) {
	
	cout << "Cargando sonidos... " << endl << flush;
	
	v_musicas.push_back( Mix_LoadMUS((path+infoSonidos.at(0).ruta).c_str()) );
	this->musicaEnReproduccion = MUSICA_DEL_NIVEL;

	for (unsigned int i=1; i < infoSonidos.size(); i++)
	{
		cout << "Sonido " << i << " de " << infoSonidos.size() << " ( " << infoSonidos.at(i).ruta << " )" << endl << flush;
		
		Mix_Chunk* musica = Mix_LoadWAV((path+infoSonidos.at(i).ruta).c_str());
		mapaSonidos[infoSonidos.at(i).idSonido] = musica;

	}
	
	int contador = 0;
	for (unsigned int i=1; i< infoSonidos.size(); i++) {
		if (infoSonidos.at(i).tipo == MUSICA_FONDO) {
			if (contador == personaje) {
				v_musicas.push_back( Mix_LoadMUS( (path+infoSonidos.at(i).ruta).c_str() ) );
				break;
			}
			else contador++;
		}
	}
}

void Vista::CrearMapaImagenes(vector<infoImagen_t> infoImagenes, string path) {

	SDL_Surface* imagen = NULL;
	
	cout << "Cargando imagenes... " << endl << flush;

	for (unsigned int i=0; i < infoImagenes.size(); i++)
	{
		cout << "Imagen " << i+1 << " de " << infoImagenes.size() << " ( " << infoImagenes.at(i).ruta << " )" << endl << flush;
		
		int anchoCuadro = infoImagenes.at(i).anchoCuadro;
		int altoCuadro = infoImagenes.at(i).altoCuadro;
		int cantCuadros = infoImagenes.at(i).cantCuadros;

		if (!infoImagenes.at(i).espejar) {
			imagen = cargar_imagen(path+infoImagenes.at(i).ruta);
			if (!imagen) {
				cout << path << infoImagenes.at(i).ruta << endl << flush;
				
				exit(0);
			}
			imagen = ajustar_imagen(imagen, anchoCuadro*cantCuadros, altoCuadro*cantCuadros);
			if (infoImagenes.at(i).angulo != 0) {
				imagen = rotar_imagen(imagen, infoImagenes.at(i).angulo);
				altoCuadro = imagen->h / cantCuadros;
				anchoCuadro = imagen->w / cantCuadros;
			}
		}
		
		else {
			// Uso la imagen que quedo del ciclo anterior, que es la no_espejada
			imagen = espejarX(imagen);
			colorKey(imagen);
		}

		Dibujable* dibujable = new Dibujable(imagen, anchoCuadro, altoCuadro, cantCuadros);
		mapaImagenes[infoImagenes.at(i).idImagen] = dibujable;

	}
	cout << "OK" << endl;

}

void Vista::setPersonajeX(int x) {
	rectPersonaje->x = x;
}

void Vista::setPersonajeY(int y) {
	rectPersonaje->y = y;
}

bool Vista::CrearFondo(idImagen_t idImagenFondo)
{
	fondoNivel = mapaImagenes[idImagenFondo]->getImagen();

    if ( altoNivel < pantalla->getAlto() )
    {
    	//LOGUEAR("El alto de la imagen de fondo fue modificado por ser menor que la pantalla.", 1);
    	if ( anchoNivel > pantalla->getAncho() )
    	{
    		fondoNivel = ajustar_imagen( fondoNivel, anchoNivel, pantalla->getAlto() );
    	} else {
    		//LOGUEAR("El ancho de la imagen de fondo fue modificado por ser menor que la pantalla.", 1);
    		fondoNivel = ajustar_imagen( fondoNivel, pantalla->getAncho(), pantalla->getAlto() );
		anchoNivel = pantalla->getAncho(); //VER ESTO !! antes se cambiaba el ancho en el modelo, que ahora es inaccesible
    	}
    } else {
    	if ( anchoNivel > pantalla->getAncho() )
    	{
    		fondoNivel = ajustar_imagen( fondoNivel, anchoNivel, altoNivel);
    	} else {
    		//LOGUEAR("El ancho de la imagen de fondo fue modificado por ser menor que la pantalla.", 1);
    		fondoNivel = ajustar_imagen( fondoNivel, pantalla->getAncho(), altoNivel);
		altoNivel = pantalla->getAncho(); //VER ESTO !! antes se cambiaba el alto en el modelo, que ahora es inaccesible
    	}
    }

    if( fondoNivel == NULL )
    {
	    //LOGUEAR("No se pudo redimensionar la imagen de Nivel.", 1);
        return false;
    }

    //LOGUEAR("El fondo fue creado.", 0);

    return true;
}

void Vista::PintarFondo(vector< pair < pair<idImagen_t, int> , Punto> > dibujables) {
	
	for (unsigned int i = 0; i< dibujables.size(); i++) {

		Dibujable* dibujable = mapaImagenes[dibujables.at(i).first.first];
		int numCuadro = dibujables.at(i).first.second;
		Punto posicion(dibujables.at(i).second.getX(), dibujables.at(i).second.getY());
		
		dibujable->Dibujar(posicion, fondoNivel, numCuadro);
		
	}

}

void Vista::elegirFondo() {
	int op = rand() % 5;
	string path_res = PATH_RES;
	switch (op) {
	case 0: {
		fondo_estatico = cargar_imagen((path_res+"dia1.bmp").c_str());
		break;
	}
	case 1: {
		fondo_estatico = cargar_imagen((path_res+"dia2.bmp").c_str());
		break;
	}
	case 2: {
		fondo_estatico = cargar_imagen((path_res+"dia3.bmp").c_str());
		break;
	}
	case 3: {
		fondo_estatico = cargar_imagen((path_res+"noche1.bmp").c_str());
		break;
	}
	case 4: {
		fondo_estatico = cargar_imagen((path_res+"noche2.bmp").c_str());
		break;
	}

	}
}

void Vista::Dibujar(vector< pair < pair<idImagen_t, int> , Punto> > dibujables) {
	
	camara->setCamara(rectPersonaje, anchoNivel, altoNivel);
	
	if (insertar_imagen (0, 0, fondo_estatico, pantalla->getSuperficie(), NULL) != 0);
		//LOGUEAR ("No se pudo insertar el fondo estatico en la pantalla.", 1);
	if (insertar_imagen (0, 0, fondoNivel, pantalla->getSuperficie(), camara->getCamara()) != 0);
		//LOGUEAR ("No se pudo insertar el fondo apuntado por la camara en la pantalla.", 1);
	
	for (unsigned int i = 0; i< dibujables.size(); i++) {
		Dibujable* dibujable = mapaImagenes[dibujables.at(i).first.first];
		int numCuadro = dibujables.at(i).first.second;
		Punto posicion(dibujables.at(i).second.getX() - camara->getX(), dibujables.at(i).second.getY() - camara->getY());
		
		dibujable->Dibujar(posicion, pantalla->getSuperficie(), numCuadro);
		
	}

}

void Vista::DibujarPuntaje(vector< pair<idImagen_t, string> > puntajes){

	if  ( puntajes.size() == 0 ) {
		    string texto = "0";
			SDL_Color white = { 255, 255, 255 };	
			SDL_Surface* mensaje = TTF_RenderText_Solid( font32, texto.c_str() , white );
			insertar_imagen(25, 25, mensaje , pantalla->getSuperficie(), NULL);	
			SDL_FreeSurface( mensaje );
			
			string vidas= "3";
			SDL_Surface* msj_vidas = TTF_RenderText_Solid( font32, vidas.c_str() , white );
			string path_res = PATH_RES;
			SDL_Surface* img_vidas = cargar_imagen((path_res+"vida_extra.bmp").c_str());
			img_vidas = ajustar_imagen(img_vidas, 30, 30);
	
	        insertar_imagen(pantalla->getAncho()- 125 , 20, img_vidas, pantalla->getSuperficie(), NULL);
			insertar_imagen(pantalla->getAncho()- 75 , 25, msj_vidas, pantalla->getSuperficie(), NULL);
			
			SDL_FreeSurface( msj_vidas );
			SDL_FreeSurface( img_vidas );
	}
	
	for (unsigned int i = 0; i< puntajes.size(); i++) {
		
		Dibujable* dibujable = mapaImagenes[puntajes.at(i).first];
		string texto = puntajes.at(i).second;

		if ( i == 0 ) {
			SDL_Color white = { 255, 255, 255 };	
			SDL_Surface* mensaje = TTF_RenderText_Solid( font32, texto.c_str() , white );
			
			insertar_imagen(25, 25, mensaje , pantalla->getSuperficie(), NULL);	
			SDL_FreeSurface( mensaje );
		} else {
			SDL_Color white = { 255, 255, 255 };
			SDL_Surface* mensaje = TTF_RenderText_Solid( font32, texto.c_str() , white );
			
			if (texto != "" ) {
				Punto posicion(pantalla->getAncho()- 100 * i - 50, 20);
				dibujable->Dibujar(posicion, pantalla->getSuperficie(), 0);
				insertar_imagen(pantalla->getAncho()- 100 * i , 25, mensaje, pantalla->getSuperficie(), NULL);
			} else {
				Punto posicion(pantalla->getAncho()- 100 * i , 25);
				dibujable->Dibujar(posicion, pantalla->getSuperficie(), 0);
			}
			
			SDL_FreeSurface( mensaje );
		}
	}
}

void Vista::DibujarBarraEstado(string mensaje) {
	
	SDL_Surface* barra = SDL_CreateRGBSurface(0, pantalla->getAncho(), 25, 32, 255, 255, 255, 0 );
	SDL_FillRect(barra, NULL, SDL_MapRGB(barra->format, 170, 170, 170));
	SDL_Color black = { 0, 0, 0 };	
	SDL_Surface* texto = TTF_RenderText_Solid( font14, mensaje.c_str() , black ); 
	
	insertar_imagen( 5, 5, texto, barra);
	insertar_imagen(0, pantalla->getAlto(), barra, pantalla->getSuperficie(), NULL);	
	SDL_Flip (pantalla->getSuperficie());
	SDL_FreeSurface( barra );
	SDL_FreeSurface( texto );
}

void Vista::InsertarCuadro() {

	SDL_Surface* fondo = SDL_CreateRGBSurface(0, 650, 500, 32, 255, 255, 255, 0 );
	SDL_FillRect(fondo, NULL, SDL_MapRGB(fondo->format, 0, 0, 0));
	string path_res = PATH_RES;
	TTF_Font* font40 = TTF_OpenFont((path_res+"fontMario.ttf").c_str(), 40 );
	SDL_Color white = {255, 255, 255};
	SDL_Surface* texto =  TTF_RenderText_Solid( font40, "CARGANDO IMAGENES..." , white);
	SDL_Surface* texto2 =  TTF_RenderText_Solid( font40, "ESPERA LOCO..." , white);

	insertar_imagen(100, 150, texto, fondo);
	insertar_imagen(100, 300, texto2, fondo);
	insertar_imagen(0, 0, fondo, pantalla->getSuperficie());
	SDL_Flip(pantalla->getSuperficie());
}

void Vista::IniciarSonido(){
	
	if( Mix_PlayingMusic() == 0 ) {

		if( Mix_PlayMusic( v_musicas.at(0), -1 ) == -1 ){
			cout<< "No se pudo iniciar musica ( Error " << Mix_GetError() << ". )" << endl << flush;
		} 
	}
}

void Vista::FinalizarSonido() {
	
	if( Mix_PlayingMusic() == 1 )
	{
		Mix_HaltMusic();
	}
	
}

void Vista::FinalizarJuego(string update) {
	
	SDL_Color black = { 0, 0, 0 };
	SDL_Color white = { 255, 255, 255 };
	SDL_Surface* cuadro = SDL_CreateRGBSurface(0, pantalla->getAncho(), pantalla->getAlto(), 32, 0, 0, 0, 0 );
	SDL_FillRect(cuadro, NULL, SDL_MapRGB(cuadro->format, 0, 0, 0));
	SDL_Surface* mensaje = TTF_RenderText_Solid( font32, update.c_str(), white );
	insertar_imagen( pantalla->getAncho()/8, pantalla->getAlto()/2, mensaje, cuadro);
	insertar_imagen( 0, 0, cuadro, pantalla->getSuperficie() );
	
	string path_res = PATH_RES;
	Mix_Chunk* musica = Mix_LoadWAV((path_res+"Fin.wav").c_str());
	Mix_PlayChannel( -1, musica, 0 );
	
	SDL_Flip(pantalla->getSuperficie());
	SDL_Delay(2000);
	
	
	SDL_FreeSurface(cuadro);
	SDL_FreeSurface(mensaje);
	
}

void Vista::ReproducirSonidos(vector< pair < pair<bool, int>, Punto> > sonidos) {
	
	bool invencibilidad = false;
	for (unsigned int i=0; i < sonidos.size(); i++ ) {
		
		if ( sonidos.at(i).first.second == MUSICA_FONDO ) {

			// Si hay que reproducir la musica de invencibilidad
			if (sonidos.at(i).first.first) {
				
				invencibilidad = true;
				
				// Si la musica en reproduccion es la del nivel
				if ( musicaEnReproduccion == MUSICA_DEL_NIVEL ) {

					if( Mix_PlayingMusic() == 1 ) 
						Mix_HaltMusic();
					
					if ( Mix_PlayingMusic() == 0 ) {

                        if ( Mix_PlayMusic( v_musicas.at(MUSICA_DE_INVENCIBILIDAD), -1 ) == -1 ) {
							cout << "No se puede reproducir musica de Invencibilidad" << endl << flush;
							musicaEnReproduccion = MUSICA_DE_INVENCIBILIDAD;
						} else {
							musicaEnReproduccion = MUSICA_DE_INVENCIBILIDAD;
						}
					}
					continue;
					
				// Si la musica en reproduccion es la de invencibilidad
				} else if ( musicaEnReproduccion == MUSICA_DE_INVENCIBILIDAD ) {
					continue;
				}
			}	
		}
		
		if ( !sonidos.at(i).first.first ) 
			continue;
		 
		if (sonidos.at(i).first.second == MUSICA_EVENTO) {
			
			if (sonidos.at(i).second.getX() < camara->getX()) continue;
			if (sonidos.at(i).second.getX() > camara->getX() + camara->getAncho()) continue;
			if (sonidos.at(i).second.getY() < camara->getY()) continue;
			if (sonidos.at(i).second.getY() > camara->getY() + camara->getAlto()) continue;
			
			Mix_Chunk* sonido = (Mix_Chunk*) mapaSonidos[i];
			Mix_PlayChannel( -1, sonido, 0 );
		}
	}
	
	if (!invencibilidad) {
		
		// Si la musica en reproduccion es la de invencibilidad
		if ( musicaEnReproduccion == MUSICA_DE_INVENCIBILIDAD ) {
			
			if( Mix_PlayingMusic() == 1 )
				Mix_HaltMusic();
			
			if ( Mix_PlayingMusic() == 0 ) {
				if ( Mix_PlayMusic( v_musicas.at(MUSICA_DEL_NIVEL), -1 ) == -1 ) {
					cout << "No se puede reproducir musica de fondo del nivel" << endl << flush;
					musicaEnReproduccion = MUSICA_DEL_NIVEL;
				} else {
					musicaEnReproduccion = MUSICA_DEL_NIVEL;
				}	
			}
		}
	}		
}
